package com.cndw.kungfu.model.pvp.camp;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import com.cndw.kungfu.config.Constants;
import com.cndw.kungfu.config.ConstantsLog;
import com.cndw.kungfu.config.ConstantsRadio;
import com.cndw.kungfu.model.PvpCommSerialize;
import com.cndw.kungfu.model.battle.Battle;
import com.cndw.kungfu.model.sys.LogServer;
import com.cndw.kungfu.vo.EventNotice;

public class CampWarEvent implements Runnable {

	@Override
	public void run() {
		try {
			synchronized (CampWar.class) {
				if (CampWar.isOpen()) {
					vs();
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private void vs() {
		Collection<CampWarPlayer> joinPlayers = CampWarBase.joinPlayers.values();

		Map<Integer, List<Long>> joinIds = new HashMap<Integer, List<Long>>();

		for (CampWarPlayer e : joinPlayers) {
			int sign = e.getSign();
			if (!joinIds.containsKey(sign)) {
				joinIds.put(sign, new ArrayList<Long>());
			}
			joinIds.get(sign).add(e.getId());
		}
		Map<Integer, Object> dataTmp = new HashMap<Integer, Object>();
		Map<Integer, Set<Long>> idsMap = new HashMap<Integer, Set<Long>>();
		for (int i = 1; i <= 3; i++) {
			List<Long> sourceIds = joinIds.get(i * 2 + 1);
			List<Long> targetIds = joinIds.get(i * 2 + 2);
			if (sourceIds == null && targetIds == null) {
				continue;
			}
			if (sourceIds == null) {
				sourceIds = new ArrayList<Long>();
			}else if (targetIds == null) {
				targetIds = new ArrayList<Long>();
			}
			Collections.shuffle(sourceIds);
			Collections.shuffle(targetIds);
			int area = i;
			List<CampWarLog> logs = new ArrayList<CampWarLog>();
			int minSize = Math.max(sourceIds.size(), targetIds.size());
			for (int j = 0; j < minSize; j++) {

				try {
					boolean npcSource = false, npcTarget = false;
					if (sourceIds.size() <= j) {
						npcSource = true;
					}
					if (targetIds.size() <= j) {
						npcTarget = true;
					}
					if (npcSource && npcTarget) {
						continue;
					}
					
					CampWarPlayerI sourceCamp = npcSource ? new CampWarNpc(area, true) : CampWarBase.joinPlayers.get(sourceIds.get(j));
					CampWarPlayerI targetCamp = npcTarget ? new CampWarNpc(area, false) : CampWarBase.joinPlayers.get(targetIds.get(j));
					if (sourceCamp == null || targetCamp == null) {
						continue;
					}

					CampWarLog record = oneBattle(area, sourceCamp, targetCamp);

					logs.add(record);

				} catch (Exception e) {
					e.printStackTrace();
				}

			}
			CampWarBase.recordsAdd(area, logs);
			Set<Long> ids = new HashSet<Long>(sourceIds);
			ids.addAll(targetIds);

			dataTmp.put(area, logs);
			idsMap.put(area, ids);

		}
		clacTop3();
		for (int i = 1; i <= 3; i++) {
			if (!dataTmp.containsKey(i)) {
				// LogUtil.getMain().debug("no camp data " + i);
				continue;
			}
			EventNotice notice = new EventNotice(ConstantsRadio.camp, ConstantsRadio.campRecords);
			notice.comitData(dataTmp.get(i));
			notice.put("topPlayers", CampWarBase.topPlayers);
			notice.broadcast(idsMap.get(i));
		}
		PvpCommSerialize.getInstance().commitSync();

	}

	private void clacTop3() {
		CampComparator comparator = new CampComparator();
		TreeSet<CampWarPlayer> treeSet = new TreeSet<CampWarPlayer>(comparator);
		treeSet.addAll(CampWar.getAllWars());
		List<Object> topPlayers = new ArrayList<Object>();
		for (int i = 0; i < 3; i++) {
			CampWarPlayer e = treeSet.pollFirst();
			if (e != null) {
				topPlayers.add(new Object[] { e.getId(), e.getSourceObj().getPlayerName(), e.isSource(), e.getStreak(), e.getWin(), e.getAll() });
			}
		}
		CampWarBase.topPlayers = topPlayers;
	}

	private CampWarLog oneBattle(int area, CampWarPlayerI sourceCamp, CampWarPlayerI targetCamp) {
		int[] hpMpS = sourceCamp.blodMagicMemory();
		int[] hpMpT = targetCamp.blodMagicMemory();
		Battle battle = new Battle(sourceCamp.getFighter(), targetCamp.getFighter());
		battle.execBattle(Constants.battle_pvpNoCost);
		battle.clear();
		sourceCamp.blodMagicMemoryRevert(hpMpS);
		targetCamp.blodMagicMemoryRevert(hpMpT);

		CampWarPlayerI winCamp = battle.getWiner() == 1 ? sourceCamp : targetCamp;
		CampWarPlayerI losCamp = battle.getWiner() == 1 ? targetCamp : sourceCamp;

		winCamp.notifyWin(true);
		losCamp.notifyWin(false);

		int areeCoef = CampConfig.awardCoefficient[area];
		int[] award = new int[5];
		award[0] = areeCoef + winCamp.getStreak() * areeCoef / 60;
		award[1] = (winCamp.getStreak() - 1) * 2 + 30;
		award[2] = areeCoef;
		award[3] = 30;
		award[4] = (winCamp.isAct() ? 1 : 0) | (losCamp.isAct() ? 2 : 0);

		CampWarLog record = new CampWarLog();
		record.setArea(area);
		record.setWinId(winCamp.getId());
		record.setWinName(winCamp.getName());
		record.setWinStreak(winCamp.getStreak());
		record.setWinSource(winCamp.isSource());

		record.setLossId(losCamp.getId());
		record.setLossName(losCamp.getName());
		record.setAward(award);

		if (winCamp.isAct()) {
			winCamp.award(award[0], award[1]);
			if (winCamp.getPlayerObj() != null) {
				battle.broadcast(winCamp.getPlayerObj());// 广播战斗
			}
		}
		if (losCamp.isAct()) {
			losCamp.award(award[2], award[3]);
			if (losCamp.getPlayerObj() != null) {
				battle.broadcast(losCamp.getPlayerObj());// 广播战斗
			}
		}
		LogServer.recordLog(winCamp.getPlayerObj(), ConstantsLog.battle, 40403, winCamp.getStreak(), winCamp.isAct(), award[0], award[1]);
		LogServer.recordLog(losCamp.getPlayerObj(), ConstantsLog.battle, 40403, losCamp.getStreak(), losCamp.isAct(), award[2], award[3]);

		if (winCamp instanceof CampWarPlayer) {
			PvpCommSerialize.getInstance().campRecordChk((CampWarPlayer) winCamp);
		}

		return record;
	}

}
